Completed
Push — master ( c898d2...a76502 )
by Rafael S.
08:20
created

index.js ➔ downsample_   A

Complexity

Conditions 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 18
rs 9.85
c 0
b 0
f 0
cc 4
1
/*
2
 * Copyright (c) 2019 Rafael da Silva Rocha.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
/**
26
 * @fileoverview The resample function.
27
 * @see https://github.com/rochars/wavefile
28
 */
29
30
import { Interpolator } from './interpolator';
31
import { FIRLPF } from './fir-lpf';
32
33
/**
34
 * Change the sample rate of the samples to a new sample rate.
35
 * @param {!Array|!TypedArray} samples The original samples.
36
 * @param {number} oldSampleRate The original sample rate.
37
 * @param {number} sampleRate The target sample rate.
38
 * @param {?Object} details The extra configuration, if needed.
39
 * @return {!Float64Array} the new samples.
40
 */
41
export function resample(
42
  samples, oldSampleRate, sampleRate, details={}) {  
43
  // Make the new sample container
44
  let rate = ((sampleRate - oldSampleRate) / oldSampleRate) + 1;
45
  let newSamples = new Float64Array(samples.length * (rate));
46
  // Create the interpolator
47
  let interpolator = new Interpolator(
48
    samples.length,
49
    newSamples.length,
50
    {
51
      method: details.method || 'cubic',
52
      tension: details.tension || 0,
53
      sincFilterSize: details.sincFilterSize || 32,
54
      sincWindow: details.sincWindow || undefined,
55
      lanczosFilterSize: details.lanczosFilterSize || 16,
56
      clip: details.clip || 'mirror'
57
    });
58
  // Upsampling
59
  if (sampleRate > oldSampleRate) {
60
    upsample_(
61
      samples, newSamples, interpolator, 
62
      sampleRate, oldSampleRate, details.LPForder || 71);
63
  // Downsampling
64
  } else {
65
    downsample_(
66
      samples, newSamples, interpolator,
67
      sampleRate, oldSampleRate, details.LPForder || 71);
68
  }
69
  return newSamples;
70
}
71
72
/**
73
 * Upsample.
74
 * @param {!Array|!TypedArray} samples The original samples.
75
 * @param {!Float64Array} newSamples The container for the new samples.
76
 * @param {Object} interpolator The interpolator.
77
 * @param {number} sampleRate The target sample rate.
78
 * @param {number} oldSampleRate The original sample rate.
79
 * @param {number} LPForder The LPF order.
80
 * @return {!Float64Array}
81
 * @private
82
 */
83
function upsample_(
84
  samples, newSamples, interpolator, sampleRate, oldSampleRate, LPForder) {
85
  // Resample and filter
86
  let filter = new FIRLPF(LPForder, sampleRate, (oldSampleRate / 2));
87
  for (let i=0; i< newSamples.length; i++) {
88
    newSamples[i] = filter.filter(interpolator.interpolate(i, samples));
89
  }
90
  // Reverse filter
91
  filter = new FIRLPF(LPForder, sampleRate, (oldSampleRate / 2));
92
  for (let i = newSamples.length - 1; i >= 0; i--) {
93
    newSamples[i]  = filter.filter(newSamples[i]);
94
  }
95
  return newSamples;
96
}
97
98
/**
99
 * Downsample.
100
 * @param {!Array|!TypedArray} samples The original samples.
101
 * @param {!Float64Array} newSamples The container for the new samples.
102
 * @param {Object} interpolator The interpolator.
103
 * @param {number} sampleRate The target sample rate.
104
 * @param {number} oldSampleRate The original sample rate.
105
 * @param {number} LPForder The LPF order.
106
 * @return {!Float64Array}
107
 * @private
108
 */
109
function downsample_(
110
  samples, newSamples, interpolator, sampleRate, oldSampleRate, LPForder) {
111
  // Filter
112
  let filter = new FIRLPF(LPForder, oldSampleRate, sampleRate / 2);
113
  for (let i = 0; i < samples.length; i++) {
114
    samples[i]  = filter.filter(samples[i]);
115
  }
116
  // Reverse filter
117
  filter = new FIRLPF(LPForder, oldSampleRate, sampleRate / 2);
118
  for (let i = samples.length - 1; i >= 0; i--) {
119
    samples[i]  = filter.filter(samples[i]);
120
  }
121
  // Resample
122
  for (let i=0; i< newSamples.length; i++) {
123
    newSamples[i] = interpolator.interpolate(i, samples);
124
  }
125
  return newSamples;
126
}
127